import warnings
warnings.filterwarnings('ignore')
from IPython.display import display
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib.pylab import rcParams
from plotly import graph_objs as go
import plotly.express as pl
import plotly.offline as pyo
from plotly.subplots import make_subplots
import seaborn as sns
from scipy import stats
import tensorflow as tf
import keras
import keras.utils
from keras.models import Model
from keras.layers import Dense, Input, Dropout, Dense, LSTM, RepeatVector,TimeDistributed
from keras import regularizers
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler
data = pd.read_csv('data/machine_0.csv')
data.columns = ['Time', 'f1', 'f2','f3','f4']
data['Time'] = pd.to_datetime(data['Time'])
data['Time'] = data['Time'].dt.floor('s')
data.head()
fig = make_subplots(rows = 2, cols=2)
fig.add_trace(go.Scatter(x=data.index, y=data["f1"],name='Feature 1'), row=1, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data["f2"],name='Feature 2'), row=1, col=2)
fig.add_trace(go.Scatter(x=data.index, y=data["f3"],name='Feature 3'), row=2, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data["f4"],name='Feature 4'), row=2, col=2)
fig.update_layout(title_text='Features')
fig.update_layout(annotations=[ dict(
x=0.5,
y=-0.15,
showarrow=False,
text="Data Index",
xref="paper",
yref="paper"
),
dict(
x=-0.07,
y=0.5,
showarrow=False,
text="Features Value Range",
textangle=-90,
xref="paper",
yref="paper"
)
])
pyo.iplot(fig)
def ma(series, win_size):
return pd.Series(data=np.convolve(a=series, v=np.ones(int(win_size))/float(win_size),
mode='same'), index=series.index)
N = 3 # Standard deviation
def threshold(series, lam):
upper = pd.Series(data=(series.mean()+(N*series.std()*(lam/(2-lam))**0.5)),index=series.index)
lower = pd.Series(data=(series.mean()-(N*series.std()*(lam/(2-lam))**0.5)),index=series.index)
return upper , lower
data_ma= pd.DataFrame()
data_ma['Time'] = data['Time']
data_ma['f1'] = ma(data['f1'],20)
data_ma['f2'] = ma(data['f2'],20)
data_ma['f3'] = ma(data['f3'],20)
data_ma['f4'] = ma(data['f4'],20)
data_ma.head()
fig = make_subplots(rows = 4, cols=1)
fig.add_trace(go.Scatter(x=data.index, y=data["f1"],name='Feature 1 ',line = dict( width=1, dash='dot')), row=1, col=1)
fig.add_trace(go.Scatter(x=data_ma.index, y=data_ma["f1"],name='Denoise Feature 1',line = dict(width=2 )), row=1, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data["f2"],name='Feature 2',line = dict( width=1, dash='dot')), row=2, col=1)
fig.add_trace(go.Scatter(x=data_ma.index, y=data_ma["f2"],name='Denoise Feature 2',line = dict(width=2 )), row=2, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data["f3"],name='Feature 3',line = dict( width=1, dash='dot')), row=3, col=1)
fig.add_trace(go.Scatter(x=data_ma.index, y=data_ma["f3"],name='Denoise Feature 3',line = dict(width=2 )), row=3, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data["f4"],name='Feature 4',line = dict( width=1, dash='dot')), row=4, col=1)
fig.add_trace(go.Scatter(x=data_ma.index, y=data_ma["f4"],name='Denoise Feature 4',line = dict(width=2 )), row=4, col=1)
fig.update_layout(title_text='Machine Sensor Data')
fig.update_layout(annotations=[ dict(
x=0.5,
y=-0.15,
showarrow=False,
text="Data Index",
xref="paper",
yref="paper"
),
dict(
x=-0.07,
y=0.5,
showarrow=False,
text="Features Value Range",
textangle=-90,
xref="paper",
yref="paper"
)
])
pyo.iplot(fig)
data_ma_diff = data_ma.diff(20)
data_ma_diff_thresh_f1= threshold(data_ma_diff['f1'], 0.9)
data_ma_diff_thresh_f2= threshold(data_ma_diff['f2'], 0.9)
data_ma_diff_thresh_f3= threshold(data_ma_diff['f3'], 0.9)
data_ma_diff_thresh_f4= threshold(data_ma_diff['f4'], 0.9)
#individual feature figure
fig_ind = go.Figure()
fig_ind.add_trace(go.Scatter(x=data.index, y=data['f1'], name='Feature 1',
line = dict( width=1, dash='dot', color='black')))
fig_ind.add_trace(go.Scatter(x=data.index, y=data_ma['f1'], name='Denoise Feature 1 ',
line = dict( width=1,color='blue')))
fig_ind.add_trace(go.Scatter(x=data.index, y=data_ma_diff_thresh_f1[0], name='upper limit',
line = dict( width=2, color='red')))
fig_ind.add_trace(go.Scatter(x=data.index, y=data_ma_diff_thresh_f1[1], name='lower limit',
line = dict( width=2, color='red')))
fig_ind.update_layout(title_text='Machine Data Feature 1',
xaxis_title="Data Index",
yaxis_title="Features Value Range"
)
pyo.iplot(fig_ind)
data_ma.head()
## LSTM Autoencoder Neural Networks
### Task 3 : Creating training and testing dataset
k = data_ma
train_size = int(len(k) * 0.7)
test_size = len(k) - train_size
train , test = k.iloc[0:train_size], k.iloc[train_size:len(k)]
scale = MinMaxScaler()
X_train = np.array(train[['f1','f2','f3','f4']])
X_test = np.array(test[['f1','f2','f3','f4']])
#calculating zscore and training value range is high
X_train = stats.zscore(X_train)
X_test = stats.zscore(X_test)
X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])
### Task 4 : Build an LSTM Autoencoder
def LSTM_NN(X):
input_shape = Input(shape=(X.shape[1], X.shape[2]))
LL1 = LSTM(128, activation='relu', return_sequences=True,
kernel_regularizer=regularizers.l2(0.00))(input_shape)
LL2 = LSTM(64, activation='relu', return_sequences=False)(LL1)
LL3 = RepeatVector(X.shape[1])(LL2)
LL4 = LSTM(64, activation='relu', return_sequences=True)(LL3)
LL5 = LSTM(128, activation='relu', return_sequences=True)(LL4)
out = TimeDistributed(Dense(X.shape[2]))(LL5)
model = Model(inputs=input_shape, outputs = out)
return model
model = LSTM_NN(X_train)
model.compile(optimizer='adam', loss='mae')
model.summary()
### Task 5 : Train the Autoencoder
n_epoch = 100
batch = 20
es = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3, mode='min')
history = model.fit(X_train, X_train,
epochs=n_epoch,
batch_size = batch,
validation_split = 0.05,
callbacks = [es],
shuffle=False).history
### Plot metrics
plt.plot(history['loss'], label='Training Loss')
plt.plot(history['val_loss'], label='Validation Loss')
plt.legend();
x_pred = model.predict(X_train)
x_pred = x_pred.reshape(x_pred.shape[0], x_pred.shape[2])
x_pred = pd.DataFrame(x_pred, columns=['f1', 'f2', 'f3', 'f4'])
x_pred.index = train.index
score = pd.DataFrame(index=train.index)
Xtrain = X_train.reshape(X_train.shape[0], X_train.shape[2])
score['Loss'] = np.mean(np.abs(x_pred - Xtrain), axis = 1)
sns.set(style='whitegrid', palette='muted')
rcParams['figure.figsize'] = 14, 8
#np.random.seed(1)
#tf.random.set_seed(1)
sns.distplot(score['Loss'], bins=50, kde=True);
Before a machine fails, it ramps into the faulty mode. Indicating faulty mode with 2 signs
This indicates warning about machine may be entering in the faulty mode
This indicates that machine is in the faulty mode, necessary actions need to be taken to prevent it from entering in Failed status
#set early warning and critical alert
warn = score['Loss'].max()
warn_thresh = (warn * 0.4).round(3)
alert_thresh = (warn_thresh * 1.4).round(3)
print('Faulty Warning : ' + str(warn_thresh))
print('Faulty Alert : ' + str(alert_thresh))
fig = plt.figure(figsize=(15,6))
plt.plot(train['f1'], label='Feature 1 with Noise')
plt.plot(x_pred['f1'], label='Prediction for feature 1 w/o noise')
plt.xlabel('Data Range')
plt.ylabel('Feature Range')
plt.legend(loc='upper left')
X_test_pred = model.predict(X_test)
X_test_pred = X_test_pred.reshape(X_test_pred.shape[0], X_test_pred.shape[2])
X_test_pred = pd.DataFrame(X_test_pred, columns=['f1', 'f2', 'f3', 'f4'])
X_test_pred.index = test.index
score_test = pd.DataFrame(index=test.index)
Xtest = X_test.reshape(X_test.shape[0], X_test.shape[2])
score_test['Loss'] = np.mean(np.abs(X_test_pred - Xtest), axis = 1)
score_test['Time'] = test['Time']
score_test['f1'] = test['f1']
score_test['f2'] = test['f2']
score_test['f3'] = test['f3']
score_test['f4'] = test['f4']
score_test['warn_thresh'] = warn_thresh
score_test['alert_thresh']= alert_thresh
score_test.loc[(score_test['Loss']>=warn_thresh)&(score_test['Loss']<alert_thresh),'Mode']='Faulty Warn'
score_test.loc[(score_test['Loss']>=alert_thresh),'Mode']='Faulty Alert'
score_test.loc[(score_test['Loss']<warn_thresh),'Mode']='Normal'
score_test.head()
fig = go.Figure()
fig.add_trace(go.Scatter(x=score_test.Time, y=score_test.Loss, mode='lines', name='Test loss'))
fig.add_trace(go.Scatter(x=score_test.Time, y=score_test.warn_thresh, mode='lines', name='Warning_Thresh'))
fig.add_trace(go.Scatter(x=score_test.Time, y=score_test.alert_thresh, mode='lines', name='Alert_Thresh'))
fig.update_layout(showlegend=True, title_text='Test Data and corresponding Thresholds',
xaxis_title="Time",
yaxis_title="Loss Range")
pyo.iplot(fig)
faulty = score_test[score_test['Mode']=='Faulty Warn']
failed = score_test[score_test['Mode']=='Faulty Alert']
scaler = StandardScaler()
scaler = scaler.fit(test[['f1']])
The below graph shows the beginning of the faulty period. There are two indications.
At the beginning of the faulty period's warnings will be given(indicated by green markers).
If the machine is not checked after fault warnings, then fault alert may get generate due to degradation in machine condition(indicated by red markers)
fig_fault = go.Figure()
fig_fault.add_trace(go.Scatter(x=faulty.Time, y=scaler.inverse_transform(faulty.f1), mode='markers',marker=dict(size=10, color='green'), name='Fault Warning'))
fig_fault.add_trace(go.Scatter(x=failed.Time, y=scaler.inverse_transform(failed.f1), mode='markers',marker=dict(size=10, color='red'), name='Fault Alert'))
fig_fault.add_trace(go.Scatter(x=faulty.Time, y=scaler.inverse_transform(faulty.f2), mode='markers',marker=dict(size=10, color='green'), name='Fault Warning'))
fig_fault.add_trace(go.Scatter(x=failed.Time, y=scaler.inverse_transform(failed.f2), mode='markers',marker=dict(size=10, color='red'), name='Fault Alert'))
fig_fault.add_trace(go.Scatter(x=faulty.Time, y=scaler.inverse_transform(faulty.f3), mode='markers',marker=dict(size=10, color='green'), name='Fault Warning'))
fig_fault.add_trace(go.Scatter(x=failed.Time, y=scaler.inverse_transform(failed.f3), mode='markers',marker=dict(size=10, color='red'), name='Fault Alert'))
fig_fault.add_trace(go.Scatter(x=faulty.Time, y=scaler.inverse_transform(faulty.f4), mode='markers',marker=dict(size=10, color='green'), name='Fault Warning'))
fig_fault.add_trace(go.Scatter(x=failed.Time, y=scaler.inverse_transform(failed.f4), mode='markers',marker=dict(size=10, color='red'), name='Fault Alert'))
fig_fault.update_layout(title_text='Time vs Fault warn',xaxis_title="Time",yaxis_title="Feature Range",showlegend=False)
pyo.iplot(fig_fault)
score_test.to_csv('Prediction_output.csv')